#include "SerialPortLogger.h"

#include <QDebug>
#include <QFileInfo>

#include "IniConfig.h"

const QString DEFAULT_SERIAL_PORT = "COM10";
const int DEFAULT_BAUD_RATE = 115200;
const int DEFAULT_DATA_BITS = 8;
const QSerialPort::Parity DEFAULT_PARITY = QSerialPort::NoParity;
const QSerialPort::StopBits DEFAULT_STOP_BITS = QSerialPort::OneStop;
const QSerialPort::FlowControl DEFAULT_FLOW_CONTROL = QSerialPort::NoFlowControl;

SerialPortLogger* SerialPortLogger::m_instance = nullptr;

SerialPortLogger& SerialPortLogger::instance()
{
    static QMutex mutex;
    QMutexLocker locker(&mutex);

    if (m_instance == nullptr) {
        m_instance = new SerialPortLogger();
    }
    return *m_instance;
}

SerialPortLogger::SerialPortLogger(QObject* parent)
    : QObject(parent),
      m_serialPort(new QSerialPort(this)),
      m_connectionTimer(new QTimer(this)),
      m_portName(DEFAULT_SERIAL_PORT),
      m_baudRate(QSerialPort::Baud9600),
      m_dataBits(QSerialPort::Data8),
      m_parity(QSerialPort::NoParity),
      m_stopBits(QSerialPort::OneStop),
      m_flowControl(QSerialPort::NoFlowControl),
      m_autoReconnect(true),
      m_reconnectInterval(5000)
{
    // 连接信号
    connect(m_serialPort, &QSerialPort::readyRead, this, &SerialPortLogger::onReadyRead);
    connect(m_serialPort, QOverload<QSerialPort::SerialPortError>::of(&QSerialPort::errorOccurred),
            this, &SerialPortLogger::onErrorOccurred);

    // 连接检查定时器
    connect(m_connectionTimer, &QTimer::timeout, this, &SerialPortLogger::checkConnection);
    m_connectionTimer->setSingleShot(false);
    m_connectionTimer->setInterval(m_reconnectInterval);

    loadConfiguration();
}

SerialPortLogger::~SerialPortLogger() { closeSerialPort(); }

bool SerialPortLogger::initialize()
{
    loadConfiguration();
    return openSerialPort();
}

void SerialPortLogger::startLogging()
{
    if (!m_serialPort->isOpen()) {
        if (openSerialPort()) {
            BoardLogger::instance().logMessage(QString("串口日志开始 - 端口: %1").arg(m_portName));
        } else {
            BoardLogger::instance().logMessage(
                QString("串口日志初始化失败 - 无法打开端口: %1").arg(m_portName));
            return;
        }
    }

    if (m_autoReconnect && !m_connectionTimer->isActive()) {
        m_connectionTimer->start();
    }
}

void SerialPortLogger::stopLogging()
{
    if (m_connectionTimer->isActive()) {
        m_connectionTimer->stop();
    }

    closeSerialPort();
    BoardLogger::instance().logMessage("串口日志停止");
}

void SerialPortLogger::sendData(const QByteArray& data)
{
    QMutexLocker locker(&m_mutex);

    if (m_serialPort && m_serialPort->isOpen()) {
        qint64 bytesWritten = m_serialPort->write(data);
        if (bytesWritten != -1) {
            BoardLogger::instance().logSerialData(m_portName, data, false);
        } else {
            BoardLogger::instance().logMessage(
                QString("发送数据失败: %1").arg(m_serialPort->errorString()));
        }
    }
}

bool SerialPortLogger::isConnected() const { return m_serialPort && m_serialPort->isOpen(); }

QString SerialPortLogger::getPortName() const { return m_portName; }

void SerialPortLogger::onReadyRead()
{
    QMutexLocker locker(&m_mutex);

    if (m_serialPort) {
        QByteArray data = m_serialPort->readAll();
        if (!data.isEmpty()) {
            // 将新数据添加到缓冲区
            m_readBuffer.append(data);

            // 处理缓冲区中的完整行
            while (true) {
                int lineEndIndex = m_readBuffer.indexOf('\n');
                if (lineEndIndex == -1) {
                    // 没有找到完整行，退出循环
                    break;
                }

                // 提取一行数据（包含换行符）
                QByteArray line = m_readBuffer.left(lineEndIndex + 1);
                m_readBuffer.remove(0, lineEndIndex + 1);

                // 记录这一行数据
                BoardLogger::instance().logSerialData(m_portName, line, true);
            }

            // 防止缓冲区无限增长，如果超过1MB清空缓冲区
            if (m_readBuffer.size() > 1024 * 1024) {
                BoardLogger::instance().logMessage(
                    QString("串口缓冲区溢出，清空缓冲区 - 端口: %1").arg(m_portName));
                m_readBuffer.clear();
            }
        }
    }
}

void SerialPortLogger::onErrorOccurred(QSerialPort::SerialPortError error)
{
    if (error != QSerialPort::NoError) {
        QString errorMsg =
            QString("串口错误 [%1]: %2").arg(m_portName).arg(m_serialPort->errorString());
        BoardLogger::instance().logMessage(errorMsg);
        qWarning() << errorMsg;

        if (error == QSerialPort::ResourceError || error == QSerialPort::DeviceNotFoundError) {
            closeSerialPort();
        }
    }
}

void SerialPortLogger::checkConnection()
{
    if (!m_serialPort->isOpen() && m_autoReconnect) {
        BoardLogger::instance().logMessage(QString("尝试重连串口: %1").arg(m_portName));
        openSerialPort();
    }
}

void SerialPortLogger::loadConfiguration()
{
    using namespace IniConfigGlobal;

    // 读取串口配置，如果不存在则使用默认值
    m_portName = getString("SerialPort/PortName", DEFAULT_SERIAL_PORT);
    m_baudRate = getInt("SerialPort/BaudRate", DEFAULT_BAUD_RATE);
    m_dataBits =
        static_cast<QSerialPort::DataBits>(getInt("SerialPort/DataBits", DEFAULT_DATA_BITS));
    m_parity = static_cast<QSerialPort::Parity>(getInt("SerialPort/Parity", DEFAULT_PARITY));
    m_stopBits =
        static_cast<QSerialPort::StopBits>(getInt("SerialPort/StopBits", DEFAULT_STOP_BITS));
    m_flowControl = static_cast<QSerialPort::FlowControl>(
        getInt("SerialPort/FlowControl", DEFAULT_FLOW_CONTROL));
    m_autoReconnect = getBool("SerialPort/AutoReconnect", true);
    m_reconnectInterval = getInt("SerialPort/ReconnectInterval", 5000);

    // 如果是首次运行，保存默认配置
    if (!hasKey("SerialPort/PortName")) {
        setValue("SerialPort/PortName", DEFAULT_SERIAL_PORT);
        setValue("SerialPort/BaudRate", DEFAULT_BAUD_RATE);
        setValue("SerialPort/DataBits", DEFAULT_DATA_BITS);
        setValue("SerialPort/Parity", static_cast<int>(DEFAULT_PARITY));
        setValue("SerialPort/StopBits", static_cast<int>(DEFAULT_STOP_BITS));
        setValue("SerialPort/FlowControl", static_cast<int>(DEFAULT_FLOW_CONTROL));
        setValue("SerialPort/AutoReconnect", true);
        setValue("SerialPort/ReconnectInterval", 5000);
        setValue("SerialPort/LogEnabled", true);
        setValue("SerialPort/LogHexData", false);

        qDebug() << "SerialPortLogger: Created default configuration in global INI";
    }
}

bool SerialPortLogger::openSerialPort()
{
    QMutexLocker locker(&m_mutex);

    if (m_serialPort->isOpen()) {
        return true;
    }

    // 检查端口是否存在
    QList<QSerialPortInfo> availablePorts = QSerialPortInfo::availablePorts();
    bool portExists = false;
    for (const QSerialPortInfo& info : availablePorts) {
        if (info.portName() == m_portName) {
            portExists = true;
            break;
        }
    }

    if (!portExists) {
        QString msg = QString("串口不存在: %1").arg(m_portName);
        qWarning() << msg;
        BoardLogger::instance().logMessage(msg);
        return false;
    }

    // 配置串口
    m_serialPort->setPortName(m_portName);
    m_serialPort->setBaudRate(m_baudRate);
    m_serialPort->setDataBits(m_dataBits);
    m_serialPort->setParity(m_parity);
    m_serialPort->setStopBits(m_stopBits);
    m_serialPort->setFlowControl(m_flowControl);

    // 打开串口
    if (m_serialPort->open(QIODevice::ReadWrite)) {
        QString msg = QString("串口连接成功: %1 (%2-%3-%4-%5)")
                          .arg(m_portName)
                          .arg(m_baudRate)
                          .arg(m_dataBits)
                          .arg(m_parity)
                          .arg(m_stopBits);
        qDebug() << msg;
        BoardLogger::instance().logMessage(msg);
        return true;
    } else {
        QString msg =
            QString("串口连接失败: %1 - %2").arg(m_portName).arg(m_serialPort->errorString());
        qWarning() << msg;
        BoardLogger::instance().logMessage(msg);
        return false;
    }
}

void SerialPortLogger::closeSerialPort()
{
    QMutexLocker locker(&m_mutex);

    if (m_serialPort && m_serialPort->isOpen()) {
        m_serialPort->close();
        // 清空读取缓冲区
        m_readBuffer.clear();
        BoardLogger::instance().logMessage(QString("串口已断开: %1").arg(m_portName));
    }
}